package com.cn.tous.resource.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.savedrequest.NullRequestCache;
/**
 * @author mengwei
 * @description ResourceServerConfig
 * @createDate 2025/7/26 16:31
 */
@Configuration
@EnableWebSecurity
@EnableMethodSecurity // 启用方法级别的安全注解
public class ResourceServerConfig {

    /**
     * 资源服务器安全过滤器链
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        commonHttpSetting(http);
        http
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers("/public/**").permitAll()  // 公开接口
                        .requestMatchers("/user/**").hasRole("USER")  // 需要USER角色
                        .requestMatchers("/admin/**").hasAnyAuthority("read", "SCOPE_read")  // 需要ADMIN角色
                        .anyRequest().authenticated()  // 其他请求需要认证
                )
                .oauth2ResourceServer(resourceServer -> resourceServer
                        .jwt(jwt -> jwt
                                .decoder(jwtDecoder()) // 使用自定义解码器（可选）
                                .jwtAuthenticationConverter(jwtAuthenticationConverter())
                        )
                );

        return http.build();
    }

    private void commonHttpSetting(HttpSecurity http) throws Exception {
        // 禁用SpringSecurity默认filter。这些filter都是非前后端分离项目的产物，用不上.
        // 表单登录/登出、session管理、csrf防护等默认配置，如果不disable。会默认创建默认filter
        http.formLogin(AbstractHttpConfigurer::disable)
                .httpBasic(AbstractHttpConfigurer::disable)
                .logout(AbstractHttpConfigurer::disable)
                .sessionManagement(AbstractHttpConfigurer::disable)
                .csrf(AbstractHttpConfigurer::disable)
                // requestCache用于重定向，前后端分析项目无需重定向，requestCache也用不上
                .requestCache(cache -> cache
                        .requestCache(new NullRequestCache())
                )
                // 无需给用户一个匿名身份
                .anonymous(AbstractHttpConfigurer::disable);

        // 处理 SpringSecurity 异常响应结果。响应数据的结构，改成业务统一的JSON结构。不要框架默认的响应结构
//        http.exceptionHandling(exceptionHandling ->
//                exceptionHandling
//                        // 认证失败异常
//                        .authenticationEntryPoint(authenticationExceptionHandler)
//                        // 鉴权失败异常
//                        .accessDeniedHandler(authorizationExceptionHandler)
//        );
//        // 其他未知异常. 尽量提前加载。
//        http.addFilterBefore(globalSpringSecurityExceptionHandler, SecurityContextHolderFilter.class);
    }

    @Bean
    public JwtAuthenticationConverter jwtAuthenticationConverter() {
        JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
        // 设置权限在JWT中的声明名称
        grantedAuthoritiesConverter.setAuthoritiesClaimName("roles");
        // 设置权限前缀
        grantedAuthoritiesConverter.setAuthorityPrefix("");

        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter);
        return jwtAuthenticationConverter;
    }

    @Bean
    public JwtDecoder jwtDecoder() {
        // 使用 JWKS URI (推荐)
        return NimbusJwtDecoder.withJwkSetUri("http://127.0.0.1:9000/oauth2/jwks").build();

        // 或者使用 issuer-uri (需要 OIDC 配置)
        // return JwtDecoders.fromIssuerLocation("http://localhost:9000");
    }

}
